package org.wxd.bi.controller;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wxd.aop.Aop;
import org.wxd.batis.excel.ExcelOut;
import org.wxd.batis.query.SortEnum;
import org.wxd.batis.sql.SqlQueryBuilder;
import org.wxd.bi.api.struct.PushColumn;
import org.wxd.bi.api.struct.PushMapping;
import org.wxd.bi.data.AppFactory;
import org.wxd.bi.data.AppService;
import org.wxd.bi.timer.CountTimeJob;
import org.wxd.lang.RunResult;
import org.wxd.lang.Tuple2;
import org.wxd.net.controller.ann.TextController;
import org.wxd.net.controller.ann.TextMapping;
import org.wxd.net.web.hs.HttpServer;
import org.wxd.net.web.hs.controller.cmd.HttpSignCheck;
import org.wxd.str.json.JsonUtil;
import org.wxd.str.json.Object2Json;
import org.wxd.timer.TimeUtil;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author: Troy.Chen(無心道, 15388152619)
 * @version: 2021-09-30 18:11
 **/
@TextController(url = "query")
public class QueryController implements Serializable, BaseQuery, HttpSignCheck {

    private static final long serialVersionUID = 1L;
    private static final Logger log = LoggerFactory.getLogger(QueryController.class);

    @Resource
    private AppFactory appFactory;

    /**
     *
     */
    @TextMapping(remarks = "统计留存")
    public RunResult loginCount() throws Exception {
        RunResult ok = RunResult.ok();
        Aop.getBean(CountTimeJob.class).count();
        return ok;
    }

    @TextMapping(remarks = "查询所有映射表名字")
    public RunResult allDataName(JSONObject params) throws Exception {
        AppService appService = appFactory.dataService(params);
        if (appService == null) {
            return RunResult.of().setMsg("验证失败");
        }
        Map<String, PushMapping> dataMappingMap = appService.getDataMappingMap();
        ArrayList<PushMapping> pushMappings = new ArrayList<>(dataMappingMap.values());
        pushMappings.sort(null);

        Map<String, Map<String, String>> titles = new LinkedHashMap<>();

        for (PushMapping pushMapping : pushMappings) {
            titles.computeIfAbsent(pushMapping.getShowGroup(), l -> new LinkedHashMap<>())
                    .put(pushMapping.getTableName(), pushMapping.getTableComment());
        }

        return RunResult.ok().setData(titles);
    }

    @TextMapping(remarks = "映射结构体")
    public RunResult title(JSONObject params) throws Exception {
        AppService appService = appFactory.dataService(params);
        if (appService == null) {
            return RunResult.of().setMsg("验证失败");
        }
        String tableName = params.getString("tableName");
        int pageSize = params.getIntValue("pageSize");
        PushMapping pushMapping = appService.getDataMappingMap().get(tableName);
        pushMapping.mapping();
        SqlQueryBuilder sqlQueryBuilder = builderWhere(params.getString("queryWhere"));
        sqlQueryBuilder.from(tableName);
        if (sqlQueryBuilder != null && log.isDebugEnabled())
            log.debug(sqlQueryBuilder.toString());

        final Tuple2<String, Object[]> tuple2 = sqlQueryBuilder.buildWhere();
        long count = appService.getAppDataHelper().getCount(tableName, tuple2.getE1(), tuple2.getE2());
        long pageMax = count / pageSize + (count % pageSize > 0 ? 1 : 0);

        RunResult ok = RunResult.ok()
                .putData("columnInfo", pushMapping.htmlColumnInfo())
                .putData("dataCount", String.valueOf(count))
                .putData("pageMax", pageMax);

        return ok;
    }

    @TextMapping(remarks = "查询数据")
    public RunResult data(JSONObject params) throws Exception {
        AppService appService = appFactory.dataService(params);
        if (appService == null) {
            return RunResult.of().setMsg("验证失败");
        }
        String tableName = params.getString("tableName");
        PushMapping pushMapping = appService.getDataMappingMap().get(tableName);
        pushMapping.mapping();

        int pageIndex = params.getIntValue("pageIndex") - 1;
        int pageSize = params.getIntValue("pageSize");
        if (pageIndex < 0) pageIndex = 0;
        List<String> datas = new LinkedList<>();

        SqlQueryBuilder sqlQueryBuilder = builderWhere(params.getString("queryWhere"));
        sqlQueryBuilder.from(tableName);
        if (pushMapping.mapping().getColumnMap().containsKey(PushColumn.SAVE_TIME.getName())) {
            sqlQueryBuilder.sort(PushColumn.SAVE_TIME.getName(), SortEnum.Max_Min);
        }
        if (pushMapping.mapping().getColumnMap().containsKey(PushColumn.ID.getName())) {
            sqlQueryBuilder.sort(PushColumn.ID.getName(), SortEnum.Max_Min);
        }
        sqlQueryBuilder.skip(pageIndex * pageSize).limit(pageSize);

        appService.getAppDataHelper().query(sqlQueryBuilder,
                (row) -> {
                    Long saveTime = row.getLong(PushColumn.SAVE_TIME.getName());
                    if (saveTime != null) {
                        try {
                            row.put(PushColumn.SAVE_TIME.getName(), TimeUtil.formatDateString("yyyy-MM-dd HH:mm:ss:SSS", saveTime));
                        } catch (Exception e) {
                        }
                    }
                    Long createTime = row.getLong(PushColumn.CREATE_TIME.getName());
                    if (createTime != null) {
                        try {
                            row.put(PushColumn.CREATE_TIME.getName(), TimeUtil.formatDateString("yyyy-MM-dd HH:mm:ss:SSS", createTime));
                        } catch (Exception e) {
                        }
                    }
                    datas.add(Object2Json.toJson(row, JsonUtil.FeaturesAllString));
                }
        );
        return RunResult.ok().putData("rows", datas);
    }

    @TextMapping(remarks = "导出excel")
    public RunResult outExcel(JSONObject params) throws Exception {
        AppService appService = appFactory.dataService(params);
        if (appService == null) {
            return RunResult.of().setMsg("验证失败");
        }

        String tableName = params.getString("tableName");

        PushMapping pushMapping = appService.getDataMappingMap().get(tableName);
        pushMapping.mapping();
        SqlQueryBuilder sqlQueryBuilder = builderWhere(params.getString("queryWhere"));
        sqlQueryBuilder.from(tableName);
        sqlQueryBuilder.sort(PushColumn.SAVE_TIME.getName(), SortEnum.Max_Min);

        RunResult ok = RunResult.ok();
        try (ExcelOut builder = ExcelOut.builder()) {
            String resourcesPath = Aop.getBean(HttpServer.class).resourcesPath();
            String excelFile = tableName + "_" + TimeUtil.formatDateString(TimeUtil.SDF_YYYYMMDDHHMMSS_4) + ".xls";
            String excelFilePath = "out/excel/" + excelFile;
            builder.createWorkbook(resourcesPath + "/" + excelFilePath)
                    .createSheet(tableName)
                    .addTitle(pushMapping.excelColumnInfo());
            appService.getAppDataHelper().query(sqlQueryBuilder,
                    (row) -> {
                        Long aLong = row.getLong(PushColumn.SAVE_TIME.getName());
                        if (aLong != null) {
                            try {
                                row.put(PushColumn.SAVE_TIME.getName(), TimeUtil.formatDateString("yyyy-MM-dd HH:mm:ss:SSS", aLong));
                            } catch (Exception e) {
                            }
                        }
                        builder.addRow(row);
                    }
            );
            ok.putData("fileName", excelFile);
            ok.putData("filePath", excelFilePath);
        }
        return ok;
    }

}
